package com.example.demo.controller;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.example.demo.entity.LotteryRecord;
import com.example.demo.entity.LotteryStock;
import com.example.demo.entity.LotteryVo;
import com.example.demo.service.ILotteryRecordService;
import com.example.demo.service.ILotteryStockService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * 前端控制器
 * </p>
 *
 * @author gexiao
 * @since 2020-12-01
 */
@Controller
public class LotteryController {
    /**
     * 600优惠券
     */
    private static final List<Integer> array600 = Arrays.asList(0, 1);
    /**
     * 800优惠券
     */
    private static final List<Integer> array800 = Arrays.asList(2, 3);
    /**
     * 1000优惠券
     */
    private static final List<Integer> array1000 = Arrays.asList(4);
    /**
     * 谢谢惠顾
     */
    private static final List<Integer> arrayNull = Arrays.asList(5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19);
    @Autowired
    private ILotteryStockService stockService;
    @Autowired
    private ILotteryRecordService recordService;


    /**
     * 库存列表
     *
     * @returnd
     */
    @GetMapping("list")
    public String  list(ModelMap map) {
        List<LotteryStock> remainList = stockService.list();
        Map<Integer, Integer> stockMap = remainList.stream().collect(Collectors.toMap(LotteryStock::getType,
                LotteryStock::getStock
        ));
        LotteryVo vo = new LotteryVo();
        for (int i = 1; i <= 4; i++) {
            Integer stock = stockMap.get(i);
            Integer hit = 0;
            int remain = stock - hit;
            if (i == 1) {
                vo.setHit600(hit);
                vo.setRemain600(remain);
            } else if (i == 2) {
                vo.setHit800(hit);
                vo.setRemain800(remain);
            } else if (i == 3) {
                vo.setHit1000(hit);
                vo.setRemain1000(remain);
            } else {
                vo.setHitNull(hit);
                vo.setRemainNull(remain);
            }
        }
        map.addAttribute("vo",vo);
        return "index";
    }
    /**
     * 清空
     *
     * @returnd
     */
    @GetMapping("remove")
    @ResponseBody
    public boolean remove() {
        return recordService.remove(new LambdaQueryWrapper<LotteryRecord>().le(LotteryRecord::getCreateTime,LocalDateTime.now() ));
    }

    /**
     * 抽奖
     *
     * @return
     */
    @GetMapping("draw")
    @ResponseBody
    public String  draw(ModelMap map) {
//        前5次（含）抽奖，可按概率随机抽出一个600元优惠券奖品，页面显示奖品中奖情况及每次抽奖结果信息
//        第6-10次抽奖，可按概率随机抽出一个600元优惠券（必须抽出），一个800元优惠券，页面显示奖品中奖情况及每次抽奖结果信息
//        第11-16次抽奖，抽出一个1000元优惠券，页面显示奖品中奖情况及每次抽奖结果信息
//        17-20次抽奖，按概率随机抽出第二个800元优惠券，页面显示奖品中奖情况及每次抽奖结果信息，20次时所有奖品必须全部抽出
        List<LotteryRecord> list = recordService.list(new LambdaQueryWrapper<LotteryRecord>().orderByAsc(LotteryRecord::getCreateTime));
        if (list != null) {
            // 先前抽奖的轮次和
            int before = list.size();
            // 当前抽奖的轮次
            int current = before + 1;
            int lotteryType;
            // 只能玩20次
            if (current > 20) {
                LotteryVo lotteryVo = buildVo(null);
                lotteryVo.setGameOver(1);
//                map.addAttribute("vo",lotteryVo);
                return JSON.toJSONString(lotteryVo);
            }
            if (before <= 4) {
                //前5次（含）抽奖，可按概率随机抽出一个600元优惠券奖品，页面显示奖品中奖情况及每次抽奖结果信息
                lotteryType = handleBefore5(list, current);
            } else if (before <= 9) {
                //第6-10次抽奖，可按概率随机抽出一个600元优惠券（必须抽出），一个800元优惠券，页面显示奖品中奖情况及每次抽奖结果信息
                lotteryType = handleBetween6And10(list, current);
            } else if (before <= 15) {
                //第11-16次抽奖，抽出一个1000元优惠券，页面显示奖品中奖情况及每次抽奖结果信息
                lotteryType = handleBetween11And16(list, current);
            } else {
                //17-20次抽奖，按概率随机抽出第二个800元优惠券，页面显示奖品中奖情况及每次抽奖结果信息，20次时所有奖品必须全部抽出
                lotteryType = handleBetween17And20(list, current);
            }

            // 写入一条记录
            LotteryRecord record = new LotteryRecord();
            record.setType(lotteryType);
            record.setCreateTime(LocalDateTime.now());
            recordService.save(record);

            // 构建返回对象
//            map.addAttribute("vo",buildVo(lotteryType));
            return JSON.toJSONString(buildVo(lotteryType));
        }
        return null;
    }

    private LotteryVo buildVo(Integer lotteryType) {
        LotteryVo vo = new LotteryVo();
        vo.setLotteryType(lotteryType);
        // 剩余的
        // type -> count
        List<LotteryStock> remainList = stockService.list();
        Map<Integer, Integer> stockMap = remainList.stream().collect(Collectors.toMap(LotteryStock::getType,
                LotteryStock::getStock
        ));
        // 命中的
        List<LotteryRecord> list = recordService.list(new LambdaQueryWrapper<LotteryRecord>().orderByAsc(LotteryRecord::getCreateTime));
        Map<Integer, Integer> hitMap = list.stream().collect(Collectors.toMap(LotteryRecord::getType,
                v -> {
                    return 1;
                },
                Integer::sum
        ));

        for (int i = 1; i <= 4; i++) {
            Integer stock = stockMap.get(i);
            Integer hit = hitMap.get(i) == null ? 0 : hitMap.get(i);
            int remain = stock - hit;
            if (i == 1) {
                vo.setHit600(hit);
                vo.setRemain600(remain);
            } else if (i == 2) {
                vo.setHit800(hit);
                vo.setRemain800(remain);
            } else if (i == 3) {
                vo.setHit1000(hit);
                vo.setRemain1000(remain);
            } else {
                vo.setHitNull(hit);
                vo.setRemainNull(remain);
            }
        }
        return vo;
    }

    private int handleBetween17And20(List<LotteryRecord> list, int current) {
        long count1000 = list.stream().filter(e -> e.getType() == 2).count();
        if (count1000 < 2) {
            // 证明没抽中过
            if (current == 20) {
                return 2;
            }
            int lotteryType = getLotteryType();
            if (lotteryType == 2) {
                return lotteryType;
            }
        }
        return 4;
    }

    private int handleBetween11And16(List<LotteryRecord> list, int current) {
        long count1000 = list.stream().filter(e -> e.getType() == 3).count();
        if (count1000 == 0) {
            // 证明没抽中过
            if (current == 16) {
                return 3;
            }
            int lotteryType = getLotteryType();
            if (lotteryType == 3) {
                return lotteryType;
            }
        }
        return 4;
    }

    private int handleBetween6And10(List<LotteryRecord> list, int current) {
        // 判断是否抽过600
        long count600 = list.stream().skip(5).filter(e -> e.getType() == 1).count();
        // 判断是否抽过800
        long count800 = list.stream().skip(5).filter(e -> e.getType() == 2).count();
        int lotteryType;
        if (count600 == 0 && count800 == 0) {
            lotteryType = getLotteryType();

            // 后面2次一定要出600或800券
            if (current == 9) {
                Double v = Math.random() * 1;
                int lottery = v.intValue();
                if (lottery == 0) {
                    return 1;
                }
                return 2;
            }
            // 可以抽600，800
            if (lotteryType != 1 && lotteryType != 2) {
                return 4;
            } else {
                return lotteryType;
            }
        } else if (count600 == 0 && count800 == 1) {
            if (current == 10) {
                // 最后次的时候一定返回600优惠券
                return 1;
            }
            lotteryType = getLotteryType();
            // 可以抽600
            if (lotteryType != 1) {
                return 4;
            } else {
                return lotteryType;
            }
        } else if (count600 == 1 && count800 == 0) {
            if (current == 10) {
                // 最后次的时候一定返回800优惠券
                return 2;
            }
            lotteryType = getLotteryType();
            // 可以抽800
            if (lotteryType != 2) {
                return 4;
            } else {
                return lotteryType;
            }
        } else {
            // 都抽过600和800了只能返回谢谢参与
            return 4;
        }

    }

    /**
     * 处理前五次
     *
     * @param list    记录列表
     * @param current 当前抽奖轮次
     */
    private int handleBefore5(List<LotteryRecord> list, int current) {
        long count = list.stream().limit(4).filter(e -> e.getType() == 1).count();
        if (count > 0) {
            //说明已经抽到过600，不能在抽600
            return 4;
        } else {
            if (current == 5) {
                // 前四次都没抽到则第五次一定是600快
                return 1;
            } else {
                //todo 只能是600，或者谢谢参与
                int lotteryType = getLotteryType();
                if (lotteryType != 1) {
                    return 4;
                }
                return lotteryType;
            }
        }
    }

    /**
     * 返回一个[0,19]的随机数
     *
     * @return
     */
    private static int getRandom() {
        Double v = Math.random() * 20;
        return v.intValue();
    }

    /**
     * 获取抽奖类别
     *
     * @return
     */
    private static int getLotteryType() {
        int random = getRandom();
        if (array600.contains(random)) {
            return 1;
        } else if (array800.contains(random)) {
            return 2;
        } else if (array1000.contains(random)) {
            return 3;
        } else if (arrayNull.contains(random)) {
            return 4;
        }
        return 0;
    }



}
